/*
 * Copyright (c) 2017.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.mybatis.generator.plugins;

import com.itfsw.mybatis.generator.plugins.utils.FormatTools;
import com.itfsw.mybatis.generator.plugins.utils.JavaElementGeneratorTools;
import com.itfsw.mybatis.generator.plugins.utils.XmlElementGeneratorTools;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.api.dom.xml.*;
import org.mybatis.generator.codegen.mybatis3.ListUtilities;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * selectByEntity插件
 * create by hedong 2020/7/9
 */
public class SelectByEntityPlugin extends PluginAdapter {

     private static final Logger LOGGER = LoggerFactory.getLogger(SelectByEntityPlugin.class);

    public static final String METHOD_SELECT_BY_ENTITY = "selectByEntity";  // 方法名

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean validate(List<String> warnings) {
        return true;
    }


    /**
     * Java Client Methods 生成
     * 具体执行顺序 http://www.mybatis.org/generator/reference/pluggingIn.html
     *
     * @param interfaze
     * @param topLevelClass
     * @param introspectedTable
     * @return
     */
    @Override
    public boolean clientGenerated(Interface interfaze, TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        String selectByEntity = introspectedTable.getTableConfiguration().getProperty("selectByEntity");
        if ("false".equals(selectByEntity)) {
            return true;
        }
        // 1. selectByEntity
        FullyQualifiedJavaType entityType = introspectedTable.getRules().calculateAllFieldsClass();
        FullyQualifiedJavaType returnType = FullyQualifiedJavaType.getNewListInstance();
        returnType.addTypeArgument(entityType);
        Method mBatchInsert = JavaElementGeneratorTools.generateMethod(
                METHOD_SELECT_BY_ENTITY,
                JavaVisibility.DEFAULT,
                returnType,
                new Parameter(entityType, "entity")

        );
        // interface 增加方法
        FormatTools.addMethodWithBestPosition(interfaze, mBatchInsert);
        LOGGER.debug("selectByEntity插件:" + interfaze.getType().getShortName() + "增加selectByEntity方法。");
        return true;
    }

    /**
     * SQL Map Methods 生成
     * 具体执行顺序 http://www.mybatis.org/generator/reference/pluggingIn.html
     *
     * @param document
     * @param introspectedTable
     * @return
     */
    @Override
    public boolean sqlMapDocumentGenerated(Document document, IntrospectedTable introspectedTable) {
        String selectByEntity = introspectedTable.getTableConfiguration().getProperty("selectByEntity");
        if ("false".equals(selectByEntity)) {
            return true;
        }

        //  selectByEntity
        XmlElement selectByEntityElement = new XmlElement("select");
        selectByEntityElement.addAttribute(new Attribute("id", METHOD_SELECT_BY_ENTITY));
        // 参数类型
        selectByEntityElement.addAttribute(new Attribute("parameterType", introspectedTable.getRules().calculateAllFieldsClass().getFullyQualifiedNameWithoutTypeParameters()));
        selectByEntityElement.addAttribute(new Attribute("resultMap", "BaseResultMap"));

        selectByEntityElement.addElement(new TextElement("select"));
        for (Element element : XmlElementGeneratorTools.generateKeys(ListUtilities.removeIdentityAndGeneratedAlwaysColumns(introspectedTable.getAllColumns()), false)) {
            selectByEntityElement.addElement(element);
        }
        selectByEntityElement.addElement(new TextElement("from " + introspectedTable.getFullyQualifiedTableNameAtRuntime()));
        XmlElement whereElement = new XmlElement("where ");
        selectByEntityElement.addElement(whereElement);

        // 添加if条件字段
        for (IntrospectedColumn column : introspectedTable.getBaseColumns()) {
            XmlElement IfElement = new XmlElement("if");
            IfElement.addAttribute(new Attribute("test", String.format("%s != null", column.getJavaProperty())));
            String typeHandler = column.getTypeHandler();
            String textValue;
            if (StringUtils.isNotBlank(typeHandler)) {
                textValue = String.format("and %s = #{%s,jdbcType=%s , typeHandler=%s}",
                        column.getActualColumnName(), column.getJavaProperty(), column.getJdbcTypeName(), typeHandler);
            } else {
                textValue = String.format("and %s = #{%s,jdbcType=%s}",
                        column.getActualColumnName(), column.getJavaProperty(), column.getJdbcTypeName());
            }
            IfElement.addElement(new TextElement(textValue));
            whereElement.addElement(IfElement);
        }

        document.getRootElement().addElement(selectByEntityElement);
        LOGGER.debug("selectByEntity插件:" + introspectedTable.getMyBatis3XmlMapperFileName() + "增加selectByEntity实现方法。");

        return true;
    }

}